const fs = require('fs')
const os = require('os')
const path = require('path')
const moment = require('moment')
const cron = require('node-cron')
const { Worker } = require('worker_threads')

// 插件入口
class MyCustomPlugin {
  constructor(config, options) {
    this.config = config // config.yml文件下middlewares配置
    this.options = options // verdaccio实例的配置
  }

  // 注册中间件
  register_middlewares(app, auth, storage) {
    /**
     * logs_path verdaccio 操作日志路径
     * storage_path .verdaccio-db.json本地包数据存储文件(storage可以直接register_middlewares接参storage上直接获取)
     */
    const { _logDir, _logName, storage_path, isPm2Hosting } = this.config

    // 私有化包列表
    const storagePlugin_list = storage?.localStorage?.storagePlugin?.data?.list

    // listen
    const listen_path = storage?.config?.listen

    /**
     * ### 添加自定义路由
     * @description: 自定义页面路由
     */
    app.get('/custom-stats', (req, res) => {
      const filePath = path.join(__dirname, 'static', 'custom-download-logs.html')
      fs.readFile(filePath, 'utf8', (err, data) => {
        if (err) {
          res.status(500).send('Error loading custom page')
        } else {
          res.send(data)
        }
      })
    })

    /**
     * ### 获取pm2 verdaccio日志接口
     * @description: verdaccio由pm2 启动, 所以需要读取pm2 verdaccio日志, 用于解析下载日志
     * 需考虑日志文件过大使用日志轮转分割存储
     */
    app.get('/api/getPm2VerdaccioLogs', async (req, res) => {
      try {
        const data = await initData()
        res.send({
          code: 0,
          msg: '读取日志记录成功',
          t: new Date().getTime(),
          data: { ...data, options: this.options, storage }
        })
      } catch (error) {
        res.status(500).send({
          code: 1,
          msg: '读取日志记录失败',
          t: new Date().getTime(),
          error: error.message
        })
      }
    })

    /**
     * ### 获取周数据
     */
    app.get('/api/getWeeklyDataByPackage', async (req, res) => {
      const { query } = req
      const { f } = query
      try {
        const data = await $utils.getWeeklyDataByPackage(f)
        res.send({
          code: 0,
          msg: '读取日志记录成功',
          t: new Date().getTime(),
          data
        })
      } catch (error) {
        res.status(500).send({
          code: 1,
          msg: '查询周下载趋势失败',
          t: new Date().getTime(),
          error: error.message
        })
      }
    })

    /**
     * ### 初始化插件
     */
    app.get('/api/initPlugins', async (req, res) => {
      try {
        $utils.initPlugins()
        res.send({
          code: 0,
          msg: '初始化成功',
          t: new Date().getTime()
        })
      } catch (error) {
        res.status(500).send({
          code: 1,
          msg: '初始化失败',
          error: error.message,
          t: new Date().getTime()
        })
      }
    })

    const useUtils = (_logDir, _logName, _dbDir = './db') => {
      /**
       * ### 同步写入文件
       * @param {*} dir 目录
       * @param {*} fileName 文件名
       * @param {*} data  数据
       */
      const asyncWriteFile = (dir, fileName, data) => {
        try {
          fs.writeFileSync(path.join(__dirname, fileName), JSON.stringify(data, null, 2))
        } catch (error) {
          const dirPath = path.join(__dirname, dir)
          fs.mkdirSync(dirPath, { recursive: true })
          fs.writeFileSync(path.join(__dirname, fileName), JSON.stringify(data, null, 2))
        }
      }

      /**
       * 同步读取文件
       * @param {*} fileName
       * @returns
       */
      const asyncReadFile = (fileName) => {
        try {
          const data = fs.readFileSync(path.join(__dirname, fileName), 'utf-8')
          return JSON.parse(data)
        } catch (error) {
          console.error(`读取 ${fileName} 失败:`, error.message)
          return null
        }
      }

      /**
       * 同步删除文件夹
       * @param {string} dirPath - 要删除的文件夹路径
       */
      const deleteFolderSync = (relativePath, isLoop) => {
        const dirPath = isLoop ? relativePath : path.join(__dirname, relativePath) // 构建绝对路径

        try {
          // 检查路径是否存在
          const stats = fs.statSync(dirPath)
          if (!stats.isDirectory()) {
            throw new Error(`路径 ${dirPath} 不是一个文件夹`)
          }

          // 读取文件夹内容
          const files = fs.readdirSync(dirPath)

          // 递归删除子文件和子文件夹
          for (const file of files) {
            const filePath = path.join(dirPath, file)

            const fileStats = fs.statSync(filePath)

            if (fileStats.isDirectory()) {
              // 如果是文件夹，递归删除
              deleteFolderSync(filePath, true)
            } else {
              // 如果是文件，直接删除
              fs.unlinkSync(filePath)
            }
          }

          // 删除空文件夹
          fs.rmdirSync(dirPath)
          // console.log(` ${dirPath} ,删除文件夹成功`)
        } catch (err) {
          // console.error(`${dirPath} 未找到,删除文件夹失败`)
          // throw err
        }
      }

      /**
       * ### 初始化插件删除缓存数据
       */
      const initPlugins = () => {
        // 默认删除db/tmp文件夹
        const dirList = ['./db', './tmp']
        dirList.forEach((dir) => {
          deleteFolderSync(dir)
        })
      }

      /**
       * ### 获取轮转日志文件列表
       * @param _logDir 日志目录
       * @param _logName 日志目录
       * @returns
       */
      const getLogDirFilesList = async () => {
        // 读取日志目录中的所有文件
        const logDirFiles = await fs.promises.readdir(_logDir)

        // 筛选出目标日志文件
        const file = logDirFiles
          .filter((file) => file.startsWith(_logName) && !file.endsWith('.gz')) // 筛选 非.gz 文件
          .map((file) => `${_logDir}/${file}`)
          .sort((a, b) => a.localeCompare(b)) // 按文件名排序

        return file
      }

      /**
       * ### 获取存储日志数据文件列表
       * @param dir 数据目录
       * @returns
       */
      const getDBDirFilesList = async (dir = 'db') => {
        let dbDirFiles = []

        // 读取日志目录中的所有文件
        const dirPath = path.join(__dirname, dir)
        try {
          dbDirFiles = await fs.promises.readdir(dirPath)
        } catch (error) {
          fs.mkdirSync(dirPath, { recursive: true })
          dbDirFiles = await fs.promises.readdir(dirPath)
        }

        // 筛选出目标日志文件
        const file = dbDirFiles.sort((a, b) => a.localeCompare(b)) // 按文件名排序

        return file
      }

      /**
       * ### 获取存储日志数据
       * @param dir 数据目录
       * @returns
       */
      const getDBStatsData = async (dir = './db') => {
        // 存储所有包的元数据
        const datebase = []
        // 读取日志目录中的所有文件
        const dbDirFiles = await fs.promises.readdir(path.join(__dirname, dir))

        dbDirFiles
          ?.sort((a, b) => a.localeCompare(b))
          ?.forEach((file) => {
            const filePath = path.join(dir, file)
            const dbPath = path.join(__dirname, filePath, 'datebase.json')

            if (fs.existsSync(dbPath)) {
              try {
                const content = fs.readFileSync(dbPath, 'utf-8')
                const db = JSON.parse(content)

                datebase.push({
                  logNo: file,
                  db
                })
              } catch (error) {
                console.error(`解析 ${file} 的 datebase.json 失败:`, error.message)
              }
            } else {
              console.warn(`db ${file} 没有 datebase.json 文件`)
            }
          })
        const filteredData = (inverse = true) => {
          return Object.fromEntries(Object.entries(mergeDatebase(datebase?.map((item) => item.db))).filter(([key, value]) => (inverse ? /\d+-\d+/.test(key) : !/\d+-\d+/.test(key))))
        }

        asyncWriteFile(`tmp`, `tmp/totalDatebase.json`, datebase)

        asyncWriteFile(`tmp`, `tmp/weeklyDatebase.json`, totalWeeklyData(filteredData()))

        return calculatePackageStats(filteredData(false))
      }

      /**
       * ### 处理按周统计数据
       * @param {*} input
       * @param {*} filter
       * @returns
       */
      const transformData = (input, filter) => {
        return Object.keys(input)
          .map((weekly) => {
            return Object.keys(input[weekly])
              .filter((name) => (filter ? name === filter : !filter))
              .map((name) => {
                const times = weekly.split('-')
                // 设置为当前年的第6周
                const sixthWeekStart = moment().year(times[0]).isoWeek(times[1]).startOf('week')
                const sixthWeekEnd = moment().year(times[0]).isoWeek(times[1]).endOf('week')
                return {
                  weekly,
                  timeRange: [sixthWeekStart.format('YYYY-MM-DD'), sixthWeekEnd.format('YYYY-MM-DD')],
                  name,
                  value: input[weekly][name]
                }
              })
          })
          .flat()
      }

      /**
       * ### 获取周统计数据
       * @returns
       */
      const getWeeklyDataByPackage = async (filter = '') => {
        const weeklyData = asyncReadFile(`tmp/weeklyDatebase.json`)
        return transformData(weeklyData, filter)
      }

      /**
       * ### 获取时间范围
       * @returns
       */
      const getTimeRange = () => {
        // 获取本周的时间范围
        const now = new Date()

        // 本日 Today
        const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate())
        const startTimestamp = startOfDay.getTime()

        const endOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1)
        endOfDay.setMilliseconds(-1)
        const endTimestamp = endOfDay.getTime()

        // 最近七天
        const lastWeek = Date.now() - 7 * 24 * 60 * 60 * 1000

        // 最近一个月
        const lastMonth = new Date()
        lastMonth.setMonth(lastMonth.getMonth() - 1)

        // 获取本周的第一天（周一）
        const startOfWeek = new Date(now)
        startOfWeek.setDate(now.getDate() - now.getDay() + 1)
        startOfWeek.setHours(0, 0, 0, 0)

        // 获取本周的最后一天（周日）
        const endOfWeek = new Date(now)
        endOfWeek.setDate(now.getDate() - now.getDay() + 7)
        endOfWeek.setHours(23, 59, 59, 999)

        // 获取本月的时间范围
        // 获取本月的第一天
        const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1)
        startOfMonth.setHours(0, 0, 0, 0)

        // 获取本月的最后一天
        const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0)
        endOfMonth.setHours(23, 59, 59, 999)

        return {
          lastWeek: [lastWeek],
          lastMonth: [new Date(lastMonth).getTime()],
          dayStats: [startTimestamp, endTimestamp],
          thisWeek: [new Date(startOfWeek).getTime(), new Date(endOfWeek).getTime()],
          thisMonth: [new Date(startOfMonth).getTime(), new Date(endOfMonth).getTime()],
          //
          dayTime: [startTimestamp, endTimestamp],
          agoTime: [lastWeek, new Date(lastMonth).getTime()],
          weekTime: [new Date(startOfWeek).getTime(), new Date(endOfWeek).getTime()],
          monthTime: [new Date(startOfMonth).getTime(), new Date(endOfMonth).getTime()]
        }
      }

      /**
       * ### 读插件package数据
       */
      const readPackagesData = () => {
        // 存储所有包的元数据
        const packagesData = []

        // 遍历插件列表
        storagePlugin_list.forEach((plugin) => {
          const pluginPath = path.join(storage_path, plugin)
          const packageJsonPath = path.join(pluginPath, 'package.json')

          // 检查是否存在 package.json 文件
          if (fs.existsSync(packageJsonPath)) {
            try {
              // 读取 package.json 文件内容
              const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf-8')
              const packageData = JSON.parse(packageJsonContent)
              const { latest } = packageData['dist-tags'] || {}
              const authorName = packageData?.versions[latest]?.author?.name || '--'

              // 将包信息添加到数组中
              packagesData.push({
                authorName,
                ...packageData
              })
            } catch (error) {
              // console.error(`解析 ${plugin} 的 package.json 失败:`, error.message)
            }
          } else {
            // console.warn(`插件 ${plugin} 没有 package.json 文件`)
          }
        })

        asyncWriteFile('tmp', `tmp/packages.json`, packagesData)
      }

      /**
       * ### 取插件package数据
       * @returns
       */
      const getPackagesData = () => {
        const fileName = `tmp/packages.json`
        return $utils.asyncReadFile(fileName)
      }

      /**
       * ### 过滤数据
       * @param {*} data
       * @param {*} result
       * @returns
       */
      const filterData = (data, result = {}) => {
        Object.entries(data).forEach(([packageName, count]) => {
          const name = decodeURIComponent(packageName)
          storagePlugin_list.forEach((pkg) => {
            if (name === pkg || (name.includes(pkg) && name.endsWith('.tgz'))) {
              result[name] = (result[name] || 0) + count
            }
          })
        })
        return result
      }

      /**
       * ### 过滤插件包更新日志数据
       * @param {*} data
       * @param {*} result
       * @returns
       */
      const filterPutLogsData = (data, result = {}) => {
        Object.entries(data).forEach(([packageName, count]) => {
          const name = decodeURIComponent(packageName)
          storagePlugin_list.forEach((pkg) => {
            if (name === pkg || (name.includes(pkg) && name.endsWith('.tgz'))) {
              result[name] = count
            }
          })
        })
        return result
      }

      /**
       * ### 过滤计算数据
       * @param {*} data
       * @param {*} result
       * @returns
       */
      const filterDatebase = (data, result = {}) => {
        Object.entries(data).forEach(([packageName, count]) => {
          const name = decodeURIComponent(packageName)
          result[name] = (result[name] || 0) + count
        })
        return result
      }

      /**
       * ### 过滤计算数据
       * @param {*} pkg
       * @param {*} data
       * @param {*} result
       * @param {*} regex
       * @returns
       */
      const filterCalculateData = (pkg, data, result = [], regex) => {
        let num = 0

        for (const key in data) {
          if (data.hasOwnProperty(key)) {
            if (key === pkg || regex.test(key)) {
              num += data[key]
              const index = result.findIndex((item) => item.packageName === key)
              if (index !== -1) return

              result.push({
                packageName: key,
                value: data[key] || 0
              })
            }
          }
        }
        return num
      }

      /**
       * ### 计算包下载量统计
       * @param {*} logs
       * @returns
       */
      const calculatePackageStats = (logs) => {
        const packageTotal = []
        const packageDetail = {}
        const lastWeekLogs = []
        const lastMonthLogs = []
        const thisWeekLogs = []
        const thisMonthLogs = []

        const packagesData = $utils.getPackagesData()

        storagePlugin_list.forEach((pkg) => {
          let totalDownloads = 0
          let totalWeekDownloads = 0
          let totalMonthDownloads = 0
          let totalthisWeekDownloads = 0
          let totalthisMonthDownloads = 0

          packageDetail[pkg] = {
            total: 0,
            details: []
          }
          const pattern = `${pkg}/-/.*.tgz`
          const regex = new RegExp(pattern)

          for (const key in logs.packages) {
            if (logs.packages.hasOwnProperty(key)) {
              if (key === pkg || regex.test(key)) {
                totalDownloads += logs.packages[key]

                packageDetail[pkg].details.push({
                  packageName: key,
                  version: key,
                  value: logs.packages[key] || '--',
                  dayDownloads: logs.dayStats[key] || '--',
                  weekDownloads: logs.lastWeek[key] || '--',
                  monthDownloads: logs.lastMonth[key] || '--',
                  thisWeekDownloads: logs.thisWeek[key] || '--',
                  thisMonthDownloads: logs.thisMonth[key] || '--'
                })
              }
            }
          }

          totalWeekDownloads = $utils.filterCalculateData(pkg, logs.lastWeek, lastWeekLogs, regex)
          totalMonthDownloads = $utils.filterCalculateData(pkg, logs.lastMonth, lastMonthLogs, regex)
          totalthisWeekDownloads = $utils.filterCalculateData(pkg, logs.thisWeek, thisWeekLogs, regex)
          totalthisMonthDownloads = $utils.filterCalculateData(pkg, logs.thisMonth, thisMonthLogs, regex)

          const packageData = packagesData.find((item) => item.name === pkg)
          packageDetail[pkg].total = totalDownloads
          packageTotal.push({
            packageName: pkg,
            version: packageData?.['dist-tags']?.['latest'] || '--',
            authorName: packageData?.['authorName'] || '--',
            value: totalDownloads,
            updateNameIp: logs.putLogs[pkg] || '--',
            totalWeekDownloads,
            totalMonthDownloads,
            totalthisWeekDownloads,
            totalthisMonthDownloads,
            details: packageDetail[pkg].details
          })
        })

        return {
          downloadLogs: packageTotal,
          config: this.config,
          tableList: {
            lastWeekLogs: lastWeekLogs.sort((a, b) => b.value - a.value),
            lastMonthLogs: lastMonthLogs.sort((a, b) => b.value - a.value),
            thisWeekLogs: thisWeekLogs.sort((a, b) => b.value - a.value),
            thisMonthLogs: thisMonthLogs.sort((a, b) => b.value - a.value)
          }
        }
      }

      // 合并 Worker 线程的结果
      const mergeResults = (results) => {
        const obj = {}
        let keyList = []

        results.forEach((i) => {
          Object.keys(i)?.forEach((j) => {
            keyList.push(j)
          })
        })

        keyList.forEach((key) => {
          obj[key] = {}
        })

        results.forEach((result) => {
          Object.keys(result)?.forEach((i) => {
            if (i === 'putLogs') {
              $utils.filterPutLogsData(result[i], obj[i])
            } else {
              $utils.filterData(result[i], obj[i])
            }
          })
        })

        return obj
      }

      // 合并 Worker 线程的结果
      const mergeDatebase = (results) => {
        const obj = {}
        let keyList = []

        results.forEach((i) => {
          Object.keys(i)?.forEach((j) => {
            keyList.push(j)
          })
        })

        keyList.forEach((key) => {
          obj[key] = {}
        })

        results.forEach((result) => {
          Object.keys(result)?.forEach((i) => {
            if (i === 'putLogs') {
              $utils.filterPutLogsData(result[i], obj[i])
            } else {
              $utils.filterDatebase(result[i], obj[i])
            }
          })
        })

        return obj
      }

      /**
       * ### 获取当前月份
       * @returns
       */
      const getCurrentMonthFormatted = () => {
        const now = new Date()
        const year = now.getFullYear()
        const month = String(now.getMonth() + 1).padStart(2, '0') // 月份从0开始，需要加1，并补零
        return `${year}${month}`
      }

      /**
       * ### 周数据求和
       * @param {*} weeklyData
       * @returns
       */
      const totalWeeklyData = (weeklyData) => {
        const filterData = {}

        storagePlugin_list.forEach((pkg) => {
          const pattern = `${pkg}/-/.*.tgz`
          const regex = new RegExp(pattern)

          for (const key in weeklyData) {
            if (!filterData[key]) {
              filterData[key] = {}
            }

            let total = 0

            for (const prop in weeklyData[key]) {
              if (prop === pkg || regex.test(prop)) {
                total += weeklyData[key][prop]
              }
            }

            if (total > 0) {
              filterData[key][pkg] = total
            }
          }
        })

        return filterData
      }

      return {
        getLogDirFilesList,
        getDBDirFilesList,
        getDBStatsData,
        getTimeRange,
        readPackagesData,
        filterData,
        filterPutLogsData,
        filterDatebase,
        filterCalculateData,
        calculatePackageStats,
        mergeResults,
        asyncWriteFile,
        asyncReadFile,
        getPackagesData,
        deleteFolderSync,
        initPlugins,
        getCurrentMonthFormatted,
        getWeeklyDataByPackage
      }
    }
    const $utils = useUtils(_logDir, _logName)

    const useWorker = () => {
      let timer = null
      let number = 0

      /**
       * ### 将日志文件拆分为多个部分
       * @param {string} logFilePath - 日志文件路径
       * @param {number} numWorkers - Worker 数量
       * @returns {Array} - 分割后的日志文件部分
       */
      const splitLogFile = (logFilePath, numWorkers) => {
        const fileSize = fs.statSync(logFilePath).size
        const num = fileSize < 1000000000 ? 1 : numWorkers
        const chunkSize = Math.ceil(fileSize / num)
        const chunks = []

        for (let i = 0; i < numWorkers; i++) {
          const start = i * chunkSize
          const end = (i + 1) * chunkSize
          chunks.push({ start, end })
        }

        return chunks
      }

      /**
       * ### 启动 Worker 线程
       * @param {string} logFilePath - 日志文件路径
       * @param {Array} chunks - 分割后的日志文件部分
       * @param {*} logNo - 日志编号
       * @returns
       */
      const startWorkers = (logFilePath, chunks, logNo) => {
        const timeRange = $utils.getTimeRange()

        return new Promise((resolve, reject) => {
          const workers = []
          const results = []
          let completedWorkers = 0

          chunks.forEach((chunk, index) => {
            const workerPath = path.resolve(__dirname, 'worker.js')
            const worker = new Worker(workerPath, {
              workerData: {
                isPm2Hosting,
                logFilePath,
                start: chunk.start,
                end: chunk.end,
                timeRange
              }
            })

            worker.on('message', (result) => {
              results[index] = result
              completedWorkers++

              // 所有 Worker 线程完成后，合并结果
              if (completedWorkers === chunks.length) {
                // 合并线程结果
                const mergedResult = $utils.mergeResults(results)
                // 数据统计
                const packageStats = $utils.calculatePackageStats(mergedResult)

                resolve(packageStats)

                const dir = `db/${logNo}`
                $utils.asyncWriteFile(`db/${logNo}`, `${dir}/results.json`, results)
                $utils.asyncWriteFile(`db/${logNo}`, `${dir}/results.json`, results)
                $utils.asyncWriteFile(`db/${logNo}`, `${dir}/datebase.json`, mergedResult)
                $utils.asyncWriteFile(`db/${logNo}`, `${dir}/stats.json`, packageStats)

                // 单次循环结束清除定时器
                if (timer) {
                  // console.log('所有 Worker 线程已完成, 读取日志文件成功')
                  clearInterval(timer)
                  timer = null
                  number = 0
                }
              }
            })

            worker.on('error', (error) => {
              console.error(`Worker ${index} 出错:`, error)
              reject(`Worker ${index} 出错:`, error)
            })

            worker.on('exit', (code) => {
              if (code !== 0) {
                console.error(`Worker ${index} 退出，代码: ${code}`)
                reject(`Worker ${index} 退出，代码: ${code}`)
              }
            })

            workers.push(worker)
          })
        })
      }

      /**
       * ### 多线程主函数
       * @param {string} file - 日志文件路径
       * @param {*} index - 日志编号
       */
      const main = async (file, index) => {
        // 获取 CPU 核心数
        const cpuCount = os.cpus().length
        // console.log(`当前电脑 CPU ${cpuCount} 核, 即将启动多线程读取日志文件`)

        timer = setInterval(() => {
          number++
          // console.log(`${number}`)
        }, 1000)

        const chunks = splitLogFile(file, cpuCount)
        await startWorkers(file, chunks, index)
      }

      return {
        main
      }
    }
    const $worker = useWorker()

    /**
     * ### 动态读取轮转日志文件
     */
    const readRotatedLogs = async () => {
      try {
        // 筛选出目标日志文件
        const logFiles = await $utils.getLogDirFilesList()

        const storageFile = await $utils.getDBDirFilesList()

        const currentMonth = $utils.getCurrentMonthFormatted()

        for (const file of logFiles) {
          // 日志编号
          const logNo = file.match(/\.(\d+)/)?.[1] || 'tmp'

          // 每次读取未轮转的实时日志
          if (!storageFile.includes(logNo) || logNo === 'tmp' || logNo == currentMonth) {
            await $worker.main(file, logNo)
          }
        }
      } catch (err) {
        console.error('读取日志失败：', err)
      }
    }

    /**
     * ### 初始化数据
     */
    const initData = async () => {
      // 解析package.json
      await $utils.readPackagesData()

      // 解析日志
      await readRotatedLogs()

      // 合并轮转日志数据
      const dbStatsData = await $utils.getDBStatsData()

      // 写入本地缓存
      $utils.asyncWriteFile(`tmp`, `tmp/dbStatsData.json`, dbStatsData)

      return dbStatsData
    }

    // 定义定时任务, 每天 22 点运行读取任务
    cron.schedule('0 22 * * *', () => {
      initData()

      const currentTime = moment().format('YYYY-MM-DD HH:mm:ss')
      // 打印日志信息, 包括时间戳和具体内容
      console.log(`[${currentTime}] Cron job executed: This task will run every day at ${currentTime}`)
    })

    console.log(`Plugin & Cron started successfully `)
    console.log(`Custom plugin page registered at ${listen_path}/custom-stats`)
  }
}

module.exports = (config, options) => new MyCustomPlugin(config, options)
